# notify_server_toast_safe.py
# ✅ 线程安全，tkinter 在主线程，使用 Queue 通信

import json
from http.server import HTTPServer, BaseHTTPRequestHandler
from socket import socket, AF_INET, SOCK_DGRAM
import threading
import tkinter as tk
from tkinter import font
import time
import queue

# ==================== 1. 全局变量 ====================
pcPort = 8080
notify_queue = queue.Queue()  # 用于线程间通信

# ==================== 2. 获取本机局域网 IP ====================
def get_local_ip():
    try:
        s = socket(AF_INET, SOCK_DGRAM)
        s.connect(("8.8.8.8", 80))
        ip = s.getsockname()[0]
        s.close()
        return ip
    except Exception:
        return "127.0.0.1"

# ==================== 3. 创建右下角弹窗（运行在主线程）====================
def show_toast(root, title, message, duration=10):
    """在主线程中显示弹窗"""
    def close_window():
        if hasattr(window, 'destroy') and window.winfo_exists():
            window.destroy()

    window = tk.Toplevel(root)
    window.title = ""
    window.overrideredirect(True)  # 去掉边框

    bg_color = "#2c3e50"
    fg_color = "white"
    win_width, win_height = 300, 100

    # 右下角位置
    x = root.winfo_screenwidth() - win_width - 20
    y = root.winfo_screenheight() - win_height - 50
    window.geometry(f"{win_width}x{win_height}+{x}+{y}")
    window.configure(bg=bg_color)

    # 字体
    title_font = font.Font(family="Microsoft YaHei", size=10, weight="bold")
    text_font = font.Font(family="Microsoft YaHei", size=9)

    tk.Label(window, text=title, bg=bg_color, fg="lightblue", font=title_font, anchor="w", padx=10).pack(fill="x", pady=(5,0))
    tk.Label(window, text=message, bg=bg_color, fg=fg_color, font=text_font, anchor="w", padx=10, wraplength=280).pack(fill="x", pady=(2,5))

    # 10秒后自动关闭
    root.after(int(duration * 1000), close_window)

# ==================== 4. HTTP 请求处理器 ====================
class NotifyHandler(BaseHTTPRequestHandler):
    def do_POST(self):
        if self.path == '/notify':
            try:
                content_length = int(self.headers.get('Content-Length', 0))
                raw_data = self.rfile.read(content_length).decode('utf-8').strip()

                print(f"🔍 收到数据: {raw_data}")

                if not raw_data:
                    self.send_response(200)
                    self.end_headers()
                    return

                data = json.loads(raw_data)
                title = data.get("title", "新消息")
                text = data.get("text", "")

                print(f"📩 解析成功: {title} - {text}")

                # ✅ 发送到主线程处理
                notify_queue.put((title, text))

                self.send_response(200)
                self.send_header('Content-Type', 'application/json')
                self.end_headers()
                self.wfile.write(b'{"status":"ok"}')

            except Exception as e:
                print(f"❌ 处理失败: {e}")
                self.send_response(500)
                self.end_headers()
        else:
            self.send_response(404)
            self.end_headers()

    def log_message(self, format, *args):
        pass

# ==================== 5. 启动 HTTP 服务器（子线程）====================
def start_server():
    server = HTTPServer(('0.0.0.0', pcPort), NotifyHandler)
    print("✅ 服务已就绪，按 Ctrl+C 停止")
    try:
        server.serve_forever()
    except:
        server.shutdown()

# ==================== 6. 主函数 ====================
# ==================== 6. 主函数 ====================
def main():
    pc_ip = get_local_ip()
    url = f"http://{pc_ip}:{pcPort}"
    print(f"🚀 通知服务器启动，监听 {url}")

    # 启动 HTTP 服务器在子线程
    server_thread = threading.Thread(target=start_server, daemon=True)
    server_thread.start()

    # 创建 tkinter 主窗口（隐藏）
    root = tk.Tk()
    root.withdraw()  # 隐藏主窗口

    # 启动时弹窗（3秒自动关闭），显示 IP 地址
    def show_welcome():
        toast = tk.Toplevel(root)
        toast.overrideredirect(True)
        toast.configure(bg="#27ae60")
        win_width, win_height = 350, 100  # 宽度加大，适应 IP 显示
        x = root.winfo_screenwidth() - win_width - 20
        y = root.winfo_screenheight() - win_height - 50
        toast.geometry(f"{win_width}x{win_height}+{x}+{y}")

        # 标题
        tk.Label(
            toast,
            text="🚀 通知桥已就绪",
            bg="#27ae60",
            fg="white",
            font=("Microsoft YaHei", 11, "bold")
        ).pack(pady=(10, 5))

        # 提示文字
        tk.Label(
            toast,
            text="请在手机脚本中设置此地址：",
            bg="#27ae60",
            fg="white",
            font=("Microsoft YaHei", 9)
        ).pack()

        # IP 地址（突出显示）
        tk.Label(
            toast,
            text=f"{pc_ip}:{pcPort}",
            bg="#27ae60",
            fg="yellow",
            font=("Consolas", 15, "bold")  # 等宽字体，更清晰
        ).pack(pady=2)

        # 3秒后自动关闭
        root.after(5000, toast.destroy)  # 显示5秒，更从容

    root.after(100, show_welcome)

    # 检查队列，处理通知
    def check_queue():
        try:
            while True:
                title, text = notify_queue.get_nowait()
                show_toast(root, title, text, duration=10)
        except queue.Empty:
            pass
        finally:
            root.after(100, check_queue)

    root.after(100, check_queue)

    # 运行 tkinter 主循环
    try:
        root.mainloop()
    except KeyboardInterrupt:
        print("\n👋 服务器已关闭")

    # 检查队列，处理通知
    def check_queue():
        try:
            while True:
                title, text = notify_queue.get_nowait()
                show_toast(root, title, text, duration=10)
        except queue.Empty:
            pass
        finally:
            root.after(100, check_queue)  # 每100ms检查一次

    root.after(100, check_queue)

    # 运行 tkinter 主循环
    try:
        root.mainloop()
    except KeyboardInterrupt:
        print("\n👋 服务器已关闭")

if __name__ == '__main__':
    main()